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 [17:0] count[NVOICES];
|
||||
reg [7:0] register[16];
|
||||
integer i;
|
||||
|
||||
always @(posedge clk) begin
|
||||
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
|
||||
outputs[i] <= outputs[i] ^ 1;
|
||||
count[i] <= 0;
|
||||
|
@ -33,7 +34,7 @@ module sound_psg(clk, reset, out, reg_sel, reg_data, reg_write);
|
|||
end
|
||||
end
|
||||
|
||||
endmodule;
|
||||
endmodule
|
||||
|
||||
module music_player(clk, reset, advance,
|
||||
psg_sel, psg_data, psg_write);
|
||||
|
|
|
@ -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 buffer, bufpos, bufferlist;
|
||||
var idrain, ifill;
|
||||
var nbuffers = 3;
|
||||
|
||||
function mix(ape) {
|
||||
var buflen=ape.outputBuffer.length;
|
||||
|
@ -381,7 +382,7 @@ var SampleAudio = function(clockfreq) {
|
|||
bufferlist = [];
|
||||
idrain = 1;
|
||||
ifill = 0;
|
||||
for (var i=0; i<3; i++) {
|
||||
for (var i=0; i<nbuffers; i++) {
|
||||
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
||||
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 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() {
|
||||
self.canvas = canvas = __createCanvas(mainElement, width, height);
|
||||
if (options && options.rotate) {
|
||||
// TODO: aspect ratio?
|
||||
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%";
|
||||
self.setRotate(options.rotate);
|
||||
}
|
||||
ctx = canvas.getContext('2d');
|
||||
imageData = ctx.createImageData(width, height);
|
||||
|
|
|
@ -4,7 +4,6 @@ var VERILOG_PRESETS = [
|
|||
{id:'clock_divider.v', name:'Clock Divider'},
|
||||
{id:'hvsync_generator.v', name:'Video Sync Generator'},
|
||||
{id:'test_hvsync.v', name:'Test Pattern'},
|
||||
{id:'lfsr.v', name:'Linear Feedback Shift Register'},
|
||||
{id:'digits10.v', name:'Bitmapped Digits'},
|
||||
{id:'7segment.v', name:'7-Segment Decoder'},
|
||||
{id:'scoreboard.v', name:'Scoreboard'},
|
||||
|
@ -17,6 +16,10 @@ var VERILOG_PRESETS = [
|
|||
{id:'sprite_rotation.v', name:'Sprite Rotation'},
|
||||
{id:'tank.v', name:'Tank Game'},
|
||||
{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([
|
||||
|
@ -62,16 +65,16 @@ var vl_stopped = false;
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
||||
|
@ -92,7 +95,7 @@ var vl_stopped = false;
|
|||
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();
|
||||
}
|
||||
|
||||
var vlSymsp = {TOPp:this};
|
||||
var vlSymsp = this; //{TOPp:this};
|
||||
var maxVclockLoop = 1;
|
||||
|
||||
this.eval = function() {
|
||||
vlSymsp.TOPp = this;
|
||||
// Initialize
|
||||
if (!vlSymsp.__Vm_didInit)
|
||||
this._eval_initial_loop(vlSymsp);
|
||||
|
@ -158,6 +160,7 @@ function VerilatorBase() {
|
|||
}
|
||||
|
||||
this._eval_initial_loop = function(vlSymsp) {
|
||||
vlSymsp.TOPp = this;
|
||||
vlSymsp.__Vm_didInit = true;
|
||||
this._eval_initial(vlSymsp);
|
||||
vlSymsp.__Vm_activity = true;
|
||||
|
@ -175,8 +178,9 @@ function VerilatorBase() {
|
|||
var VerilogPlatform = function(mainElement, options) {
|
||||
var self = this;
|
||||
var video, audio;
|
||||
var videoWidth = 304;
|
||||
var videoHeight = 248;
|
||||
var useAudio = false;
|
||||
var videoWidth = 256+16;
|
||||
var videoHeight = 240+16;
|
||||
var maxVideoBlankLines = 80;
|
||||
var idata, timer;
|
||||
var gen;
|
||||
|
@ -219,11 +223,14 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
|
||||
function vidtick() {
|
||||
gen.tick2();
|
||||
audio.feedSample((gen.spkr&255)*(1.0/255.0), 1);
|
||||
if (debugCond && debugCond()) debugCond = null;
|
||||
if (useAudio)
|
||||
audio.feedSample(gen.spkr*(1.0/255.0), 1);
|
||||
if (debugCond && debugCond())
|
||||
debugCond = null;
|
||||
}
|
||||
|
||||
function updateInspectionFrame() {
|
||||
useAudio = false;
|
||||
if (inspect_obj && inspect_sym) {
|
||||
var COLOR_BIT_OFF = 0xffff3333;
|
||||
var COLOR_BIT_ON = 0xffffffff;
|
||||
|
@ -251,8 +258,9 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
}
|
||||
|
||||
function updateVideoFrame() {
|
||||
useAudio = gen.spkr !== 'undefined';
|
||||
debugCond = self.getDebugCallback();
|
||||
var i=4; // TODO, start @ 0?
|
||||
var i=videoWidth-10;
|
||||
var trace=inspect_obj && inspect_sym;
|
||||
gen.switches_p1 = switches[0];
|
||||
gen.switches_p2 = switches[1];
|
||||
|
@ -265,7 +273,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
if (trace) {
|
||||
inspect_data[i] = inspect_obj[inspect_sym];
|
||||
}
|
||||
idata[i++] = RGBLOOKUP[gen.rgb];
|
||||
idata[i++] = RGBLOOKUP[gen.rgb & 7];
|
||||
}
|
||||
var z=0;
|
||||
while (!gen.hsync && z++<videoWidth) vidtick();
|
||||
|
@ -321,14 +329,12 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
fillTraceBuffer(Math.floor(videoWidth/4) * arr.length);
|
||||
if (!dirty) return;
|
||||
dirty = false;
|
||||
for (var i=0; i<idata.length; i++) {
|
||||
if (idata[i])
|
||||
idata[i] = 0; //<<= 1;
|
||||
}
|
||||
var COLOR_BLACK = 0xff000000;
|
||||
var COLOR_SIGNAL = 0xff22ff22;
|
||||
var COLOR_BORDER = 0xff662222;
|
||||
var COLOR_TRANS_SIGNAL = 0xff226622;
|
||||
var COLOR_BLIP_SIGNAL = 0xff226622;
|
||||
idata.fill(COLOR_BLACK);
|
||||
var jstart = scope_x_offset * arr.length;
|
||||
var j = jstart;
|
||||
for (var x=0; x<videoWidth; x++) {
|
||||
|
@ -419,12 +425,12 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
$(video.canvas).mousedown(function(e) {
|
||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16);
|
||||
mouse_pressed = true;
|
||||
e.target.setCapture();
|
||||
if (e.target.setCapture) e.target.setCapture();
|
||||
dirty = true;
|
||||
});
|
||||
$(video.canvas).mouseup(function(e) {
|
||||
mouse_pressed = false;
|
||||
e.target.releaseCapture();
|
||||
if (e.target.setCapture) e.target.releaseCapture();
|
||||
});
|
||||
audio = new SampleAudio(AUDIO_FREQ);
|
||||
idata = video.getFrameData();
|
||||
|
@ -492,6 +498,8 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
trace_index = scope_x_offset = 0;
|
||||
trace_buffer.fill(0);
|
||||
dirty = true;
|
||||
console.log(gen.rotate);
|
||||
video.setRotate(gen.rotate ? -90 : 0);
|
||||
}
|
||||
this.tick = function() {
|
||||
gen.tick2();
|
||||
|
|
|
@ -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