mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-09-29 06:55:37 +00:00
minor changes; preset changes; rotate output
This commit is contained in:
parent
8c3939ac6c
commit
89b1c64ac8
@ -1,19 +1,23 @@
|
|||||||
module LFSR8_11D(
|
|
||||||
input clk,
|
|
||||||
output reg [7:0] LFSR = 255 // put here the initial value
|
|
||||||
);
|
|
||||||
|
|
||||||
wire feedback = LFSR[7];
|
module LFSR(clk,reset,enable,lfsr);
|
||||||
|
|
||||||
|
parameter NBITS = 8;
|
||||||
|
parameter TAPS = 8'b11101;
|
||||||
|
parameter INVERT = 0;
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
input enable;
|
||||||
|
output reg [NBITS-1:0] lfsr;
|
||||||
|
|
||||||
|
wire feedback = lfsr[NBITS-1] ^ INVERT;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if (reset) // initialize to 1
|
||||||
|
lfsr <= {lfsr[NBITS-2:1], 1'b0, 1'b1};
|
||||||
|
else if (enable)
|
||||||
|
lfsr <= {lfsr[NBITS-2:0], 1'b0} ^ (feedback ? TAPS : 0);
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule;
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
LFSR[0] <= feedback;
|
|
||||||
LFSR[1] <= LFSR[0];
|
|
||||||
LFSR[2] <= LFSR[1] ^ feedback;
|
|
||||||
LFSR[3] <= LFSR[2] ^ feedback;
|
|
||||||
LFSR[4] <= LFSR[3] ^ feedback;
|
|
||||||
LFSR[5] <= LFSR[4];
|
|
||||||
LFSR[6] <= LFSR[5];
|
|
||||||
LFSR[7] <= LFSR[6];
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
|
@ -13,10 +13,11 @@ module sound_psg(clk, reset, out, reg_sel, reg_data, reg_write);
|
|||||||
reg outputs[NVOICES];
|
reg outputs[NVOICES];
|
||||||
reg [17:0] count[NVOICES];
|
reg [17:0] count[NVOICES];
|
||||||
reg [7:0] register[16];
|
reg [7:0] register[16];
|
||||||
|
integer i;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
out = 0;
|
out = 0;
|
||||||
for (int i=0; i<NVOICES; i++) begin
|
for (i=0; i<NVOICES; i++) begin
|
||||||
if (count[i][17:6] == {register[i*2+1][3:0], register[i*2]}) begin
|
if (count[i][17:6] == {register[i*2+1][3:0], register[i*2]}) begin
|
||||||
outputs[i] <= outputs[i] ^ 1;
|
outputs[i] <= outputs[i] ^ 1;
|
||||||
count[i] <= 0;
|
count[i] <= 0;
|
||||||
@ -33,7 +34,7 @@ module sound_psg(clk, reset, out, reg_sel, reg_data, reg_write);
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule;
|
endmodule
|
||||||
|
|
||||||
module music_player(clk, reset, advance,
|
module music_player(clk, reset, advance,
|
||||||
psg_sel, psg_data, psg_write);
|
psg_sel, psg_data, psg_write);
|
||||||
|
39
presets/verilog/starfield.v
Normal file
39
presets/verilog/starfield.v
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
`include "hvsync_generator.v"
|
||||||
|
`include "lfsr.v"
|
||||||
|
|
||||||
|
module top(clk, reset, hsync, vsync, rgb);
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
output hsync, vsync;
|
||||||
|
output [2:0] rgb;
|
||||||
|
wire display_on;
|
||||||
|
wire [8:0] hpos;
|
||||||
|
wire [8:0] vpos;
|
||||||
|
wire [15:0] lfsr;
|
||||||
|
|
||||||
|
hvsync_generator hvsync_gen(
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.hsync(hsync),
|
||||||
|
.vsync(vsync),
|
||||||
|
.display_on(display_on),
|
||||||
|
.hpos(hpos),
|
||||||
|
.vpos(vpos)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire star_enable = !hpos[8] & !vpos[8];
|
||||||
|
|
||||||
|
// LFSR with period = 2^16-1 = 256*256-1
|
||||||
|
LFSR #(16,16'b1000000001011,0) lfsr_gen(
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.enable(star_enable),
|
||||||
|
.lfsr(lfsr));
|
||||||
|
|
||||||
|
wire star_on = &lfsr[15:9];
|
||||||
|
wire r = display_on && star_on && lfsr[0];
|
||||||
|
wire g = display_on && star_on && lfsr[1];
|
||||||
|
wire b = display_on && star_on && lfsr[2];
|
||||||
|
assign rgb = {b,g,r};
|
||||||
|
|
||||||
|
endmodule
|
@ -312,6 +312,7 @@ var SampleAudio = function(clockfreq) {
|
|||||||
var sfrac, sinc, accum;
|
var sfrac, sinc, accum;
|
||||||
var buffer, bufpos, bufferlist;
|
var buffer, bufpos, bufferlist;
|
||||||
var idrain, ifill;
|
var idrain, ifill;
|
||||||
|
var nbuffers = 3;
|
||||||
|
|
||||||
function mix(ape) {
|
function mix(ape) {
|
||||||
var buflen=ape.outputBuffer.length;
|
var buflen=ape.outputBuffer.length;
|
||||||
@ -381,7 +382,7 @@ var SampleAudio = function(clockfreq) {
|
|||||||
bufferlist = [];
|
bufferlist = [];
|
||||||
idrain = 1;
|
idrain = 1;
|
||||||
ifill = 0;
|
ifill = 0;
|
||||||
for (var i=0; i<3; i++) {
|
for (var i=0; i<nbuffers; i++) {
|
||||||
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
||||||
bufferlist[i] = new Float32Array(arrbuf);
|
bufferlist[i] = new Float32Array(arrbuf);
|
||||||
}
|
}
|
||||||
|
19
src/emu.js
19
src/emu.js
@ -31,15 +31,22 @@ var RasterVideo = function(mainElement, width, height, options) {
|
|||||||
var canvas, ctx;
|
var canvas, ctx;
|
||||||
var imageData, arraybuf, buf8, datau32;
|
var imageData, arraybuf, buf8, datau32;
|
||||||
|
|
||||||
|
this.setRotate = function(rotate) {
|
||||||
|
if (rotate) {
|
||||||
|
// TODO: aspect ratio?
|
||||||
|
canvas.style.transform = "rotate("+rotate+"deg)";
|
||||||
|
if (canvas.width < canvas.height)
|
||||||
|
canvas.style.paddingLeft = canvas.style.paddingRight = "10%";
|
||||||
|
} else {
|
||||||
|
canvas.style.transform = null;
|
||||||
|
canvas.style.paddingLeft = canvas.style.paddingRight = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.create = function() {
|
this.create = function() {
|
||||||
self.canvas = canvas = __createCanvas(mainElement, width, height);
|
self.canvas = canvas = __createCanvas(mainElement, width, height);
|
||||||
if (options && options.rotate) {
|
if (options && options.rotate) {
|
||||||
// TODO: aspect ratio?
|
self.setRotate(options.rotate);
|
||||||
canvas.style.transform = "rotate("+options.rotate+"deg)";
|
|
||||||
if (canvas.width < canvas.height)
|
|
||||||
canvas.style.paddingLeft = canvas.style.paddingRight = "10%";
|
|
||||||
//else
|
|
||||||
// canvas.style.paddingTop = canvas.style.paddingBottom = "10%";
|
|
||||||
}
|
}
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
imageData = ctx.createImageData(width, height);
|
imageData = ctx.createImageData(width, height);
|
||||||
|
@ -4,7 +4,6 @@ var VERILOG_PRESETS = [
|
|||||||
{id:'clock_divider.v', name:'Clock Divider'},
|
{id:'clock_divider.v', name:'Clock Divider'},
|
||||||
{id:'hvsync_generator.v', name:'Video Sync Generator'},
|
{id:'hvsync_generator.v', name:'Video Sync Generator'},
|
||||||
{id:'test_hvsync.v', name:'Test Pattern'},
|
{id:'test_hvsync.v', name:'Test Pattern'},
|
||||||
{id:'lfsr.v', name:'Linear Feedback Shift Register'},
|
|
||||||
{id:'digits10.v', name:'Bitmapped Digits'},
|
{id:'digits10.v', name:'Bitmapped Digits'},
|
||||||
{id:'7segment.v', name:'7-Segment Decoder'},
|
{id:'7segment.v', name:'7-Segment Decoder'},
|
||||||
{id:'scoreboard.v', name:'Scoreboard'},
|
{id:'scoreboard.v', name:'Scoreboard'},
|
||||||
@ -17,6 +16,10 @@ var VERILOG_PRESETS = [
|
|||||||
{id:'sprite_rotation.v', name:'Sprite Rotation'},
|
{id:'sprite_rotation.v', name:'Sprite Rotation'},
|
||||||
{id:'tank.v', name:'Tank Game'},
|
{id:'tank.v', name:'Tank Game'},
|
||||||
{id:'cpu8.v', name:'Simple 8-Bit CPU'},
|
{id:'cpu8.v', name:'Simple 8-Bit CPU'},
|
||||||
|
{id:'race_game_cpu.v', name:'Race Game With CPU'},
|
||||||
|
{id:'music.v', name:'3-Voice Music'},
|
||||||
|
{id:'lfsr.v', name:'Linear Feedback Shift Register'},
|
||||||
|
{id:'starfield.v', name:'Scrolling Starfield'},
|
||||||
];
|
];
|
||||||
|
|
||||||
var VERILOG_KEYCODE_MAP = makeKeycodeMap([
|
var VERILOG_KEYCODE_MAP = makeKeycodeMap([
|
||||||
@ -62,16 +65,16 @@ var vl_stopped = false;
|
|||||||
var VL_NEGATE_I = this.VL_NEGATE_I = function(x) { return -x; }
|
var VL_NEGATE_I = this.VL_NEGATE_I = function(x) { return -x; }
|
||||||
|
|
||||||
var VL_LTS_III = this.VL_LTS_III = function(x,lbits,y,lhs,rhs) {
|
var VL_LTS_III = this.VL_LTS_III = function(x,lbits,y,lhs,rhs) {
|
||||||
return VL_EXTENDS_II(x,lbits,lhs) < VL_EXTENDS_II(x,lbits,rhs); }
|
return 0 | (VL_EXTENDS_II(x,lbits,lhs) < VL_EXTENDS_II(x,lbits,rhs)); }
|
||||||
|
|
||||||
var VL_GTS_III = this.VL_GTS_III = function(x,lbits,y,lhs,rhs) {
|
var VL_GTS_III = this.VL_GTS_III = function(x,lbits,y,lhs,rhs) {
|
||||||
return VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs); }
|
return 0 | (VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs)); }
|
||||||
|
|
||||||
var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) {
|
var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) {
|
||||||
return VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs); }
|
return 0 | (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)); }
|
||||||
|
|
||||||
var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) {
|
var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) {
|
||||||
return VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs); }
|
return 0 | (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)); }
|
||||||
|
|
||||||
var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
|
var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
|
||||||
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
||||||
@ -92,7 +95,7 @@ var vl_stopped = false;
|
|||||||
vl_stopped = true;
|
vl_stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var VL_RAND_RESET_I = this.VL_RAND_RESET_I = function(bits) { return Math.floor(Math.random() * (1<<bits)); }
|
var VL_RAND_RESET_I = this.VL_RAND_RESET_I = function(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -131,11 +134,10 @@ function VerilatorBase() {
|
|||||||
this.eval();
|
this.eval();
|
||||||
}
|
}
|
||||||
|
|
||||||
var vlSymsp = {TOPp:this};
|
var vlSymsp = this; //{TOPp:this};
|
||||||
var maxVclockLoop = 1;
|
var maxVclockLoop = 1;
|
||||||
|
|
||||||
this.eval = function() {
|
this.eval = function() {
|
||||||
vlSymsp.TOPp = this;
|
|
||||||
// Initialize
|
// Initialize
|
||||||
if (!vlSymsp.__Vm_didInit)
|
if (!vlSymsp.__Vm_didInit)
|
||||||
this._eval_initial_loop(vlSymsp);
|
this._eval_initial_loop(vlSymsp);
|
||||||
@ -158,6 +160,7 @@ function VerilatorBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._eval_initial_loop = function(vlSymsp) {
|
this._eval_initial_loop = function(vlSymsp) {
|
||||||
|
vlSymsp.TOPp = this;
|
||||||
vlSymsp.__Vm_didInit = true;
|
vlSymsp.__Vm_didInit = true;
|
||||||
this._eval_initial(vlSymsp);
|
this._eval_initial(vlSymsp);
|
||||||
vlSymsp.__Vm_activity = true;
|
vlSymsp.__Vm_activity = true;
|
||||||
@ -175,8 +178,9 @@ function VerilatorBase() {
|
|||||||
var VerilogPlatform = function(mainElement, options) {
|
var VerilogPlatform = function(mainElement, options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var video, audio;
|
var video, audio;
|
||||||
var videoWidth = 304;
|
var useAudio = false;
|
||||||
var videoHeight = 248;
|
var videoWidth = 256+16;
|
||||||
|
var videoHeight = 240+16;
|
||||||
var maxVideoBlankLines = 80;
|
var maxVideoBlankLines = 80;
|
||||||
var idata, timer;
|
var idata, timer;
|
||||||
var gen;
|
var gen;
|
||||||
@ -219,11 +223,14 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
|
|
||||||
function vidtick() {
|
function vidtick() {
|
||||||
gen.tick2();
|
gen.tick2();
|
||||||
audio.feedSample((gen.spkr&255)*(1.0/255.0), 1);
|
if (useAudio)
|
||||||
if (debugCond && debugCond()) debugCond = null;
|
audio.feedSample(gen.spkr*(1.0/255.0), 1);
|
||||||
|
if (debugCond && debugCond())
|
||||||
|
debugCond = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateInspectionFrame() {
|
function updateInspectionFrame() {
|
||||||
|
useAudio = false;
|
||||||
if (inspect_obj && inspect_sym) {
|
if (inspect_obj && inspect_sym) {
|
||||||
var COLOR_BIT_OFF = 0xffff3333;
|
var COLOR_BIT_OFF = 0xffff3333;
|
||||||
var COLOR_BIT_ON = 0xffffffff;
|
var COLOR_BIT_ON = 0xffffffff;
|
||||||
@ -251,8 +258,9 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateVideoFrame() {
|
function updateVideoFrame() {
|
||||||
|
useAudio = gen.spkr !== 'undefined';
|
||||||
debugCond = self.getDebugCallback();
|
debugCond = self.getDebugCallback();
|
||||||
var i=4; // TODO, start @ 0?
|
var i=videoWidth-10;
|
||||||
var trace=inspect_obj && inspect_sym;
|
var trace=inspect_obj && inspect_sym;
|
||||||
gen.switches_p1 = switches[0];
|
gen.switches_p1 = switches[0];
|
||||||
gen.switches_p2 = switches[1];
|
gen.switches_p2 = switches[1];
|
||||||
@ -265,7 +273,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
if (trace) {
|
if (trace) {
|
||||||
inspect_data[i] = inspect_obj[inspect_sym];
|
inspect_data[i] = inspect_obj[inspect_sym];
|
||||||
}
|
}
|
||||||
idata[i++] = RGBLOOKUP[gen.rgb];
|
idata[i++] = RGBLOOKUP[gen.rgb & 7];
|
||||||
}
|
}
|
||||||
var z=0;
|
var z=0;
|
||||||
while (!gen.hsync && z++<videoWidth) vidtick();
|
while (!gen.hsync && z++<videoWidth) vidtick();
|
||||||
@ -321,14 +329,12 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
fillTraceBuffer(Math.floor(videoWidth/4) * arr.length);
|
fillTraceBuffer(Math.floor(videoWidth/4) * arr.length);
|
||||||
if (!dirty) return;
|
if (!dirty) return;
|
||||||
dirty = false;
|
dirty = false;
|
||||||
for (var i=0; i<idata.length; i++) {
|
var COLOR_BLACK = 0xff000000;
|
||||||
if (idata[i])
|
|
||||||
idata[i] = 0; //<<= 1;
|
|
||||||
}
|
|
||||||
var COLOR_SIGNAL = 0xff22ff22;
|
var COLOR_SIGNAL = 0xff22ff22;
|
||||||
var COLOR_BORDER = 0xff662222;
|
var COLOR_BORDER = 0xff662222;
|
||||||
var COLOR_TRANS_SIGNAL = 0xff226622;
|
var COLOR_TRANS_SIGNAL = 0xff226622;
|
||||||
var COLOR_BLIP_SIGNAL = 0xff226622;
|
var COLOR_BLIP_SIGNAL = 0xff226622;
|
||||||
|
idata.fill(COLOR_BLACK);
|
||||||
var jstart = scope_x_offset * arr.length;
|
var jstart = scope_x_offset * arr.length;
|
||||||
var j = jstart;
|
var j = jstart;
|
||||||
for (var x=0; x<videoWidth; x++) {
|
for (var x=0; x<videoWidth; x++) {
|
||||||
@ -419,12 +425,12 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
$(video.canvas).mousedown(function(e) {
|
$(video.canvas).mousedown(function(e) {
|
||||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16);
|
scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16);
|
||||||
mouse_pressed = true;
|
mouse_pressed = true;
|
||||||
e.target.setCapture();
|
if (e.target.setCapture) e.target.setCapture();
|
||||||
dirty = true;
|
dirty = true;
|
||||||
});
|
});
|
||||||
$(video.canvas).mouseup(function(e) {
|
$(video.canvas).mouseup(function(e) {
|
||||||
mouse_pressed = false;
|
mouse_pressed = false;
|
||||||
e.target.releaseCapture();
|
if (e.target.setCapture) e.target.releaseCapture();
|
||||||
});
|
});
|
||||||
audio = new SampleAudio(AUDIO_FREQ);
|
audio = new SampleAudio(AUDIO_FREQ);
|
||||||
idata = video.getFrameData();
|
idata = video.getFrameData();
|
||||||
@ -492,6 +498,8 @@ var VerilogPlatform = function(mainElement, options) {
|
|||||||
trace_index = scope_x_offset = 0;
|
trace_index = scope_x_offset = 0;
|
||||||
trace_buffer.fill(0);
|
trace_buffer.fill(0);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
console.log(gen.rotate);
|
||||||
|
video.setRotate(gen.rotate ? -90 : 0);
|
||||||
}
|
}
|
||||||
this.tick = function() {
|
this.tick = function() {
|
||||||
gen.tick2();
|
gen.tick2();
|
||||||
|
28
tools/lfsrcalc.py
Executable file
28
tools/lfsrcalc.py
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
print "Period,nbits,feedback,mask"
|
||||||
|
|
||||||
|
for n in range(1,18):
|
||||||
|
mask = (1<<n)-1
|
||||||
|
hibit = (1<<(n-1))
|
||||||
|
for i in range(0,1<<n):
|
||||||
|
for invert in [0,1]:
|
||||||
|
x = 1
|
||||||
|
seq = []
|
||||||
|
seen = set()
|
||||||
|
while x and not x in seen:
|
||||||
|
seq.append(x)
|
||||||
|
seen.add(x)
|
||||||
|
feedback = x & hibit
|
||||||
|
x = ((x << 1) & mask)
|
||||||
|
if invert:
|
||||||
|
if not feedback:
|
||||||
|
x ^= i
|
||||||
|
else:
|
||||||
|
if feedback:
|
||||||
|
x ^= i
|
||||||
|
if x:
|
||||||
|
seqindex = seq.index(x)
|
||||||
|
seqlen = len(seq) - seqindex
|
||||||
|
if seqlen>1:
|
||||||
|
print seqlen, "#(%d,%d'%s,%d)" % (n,n,bin(i)[1:],invert), seqindex
|
Loading…
Reference in New Issue
Block a user